package net.realsee.service.wcs.intf.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import net.realsee.common.constant.CacheNames;
import net.realsee.common.exception.ServiceException;
import net.realsee.common.utils.StringUtils;
import net.realsee.common.utils.redis.CacheUtils;
import net.realsee.domain.wcs.intf.WcsExtApp;
import net.realsee.domain.wcs.intf.bo.WcsAppClassBo;
import net.realsee.domain.wcs.intf.bo.WcsExtAppBo;
import net.realsee.domain.wcs.intf.vo.WcsAppClassVo;
import net.realsee.domain.wcs.intf.vo.WcsExtAppVo;
import net.realsee.framework.core.domain.PageQuery;
import net.realsee.framework.core.page.TableDataInfo;
import net.realsee.mapper.wcs.intf.WcsExtAppMapper;
import net.realsee.service.wcs.intf.IWcsAppClassService;
import net.realsee.service.wcs.intf.IWcsExtAppService;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * 外部系统定义Service业务层处理
 *
 * @author realsee
 * @date 2023-08-11
 */
@RequiredArgsConstructor
@Service
public class WcsExtAppServiceImpl extends ServiceImpl<WcsExtAppMapper, WcsExtApp> implements IWcsExtAppService {

    private final WcsExtAppMapper baseMapper;
    private final IWcsAppClassService appClassService;

    /**
     * 查询外部系统定义
     */
    @Override
    public WcsExtAppVo selectVoById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询外部系统定义
     */
    @Cacheable(cacheNames = CacheNames.EXT_APP_CODE, key = "#appCode")
    @Override
    public WcsExtApp getByAppCode(String appCode) {
        return this.lambdaQuery().eq(WcsExtApp::getAppCode, appCode).last("limit 1").one();
    }

    /**
     * 查询外部系统定义列表
     */
    @Override
    public TableDataInfo<WcsExtAppVo> selectVoPage(WcsExtAppBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<WcsExtApp> lqw = buildVoQueryWrapper(bo);
        Page<WcsExtAppVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询外部系统定义列表
     */
    @Override
    public List<WcsExtAppVo> selectVoList(WcsExtAppBo bo) {
        LambdaQueryWrapper<WcsExtApp> lqw = buildVoQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<WcsExtApp> buildVoQueryWrapper(WcsExtAppBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<WcsExtApp> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getId() != null, WcsExtApp::getId, bo.getId());
        lqw.eq(StringUtils.isNotBlank(bo.getAppCode()), WcsExtApp::getAppCode, bo.getAppCode());
        lqw.eq(StringUtils.isNotBlank(bo.getAppClass()), WcsExtApp::getAppClass, bo.getAppClass());
        lqw.like(StringUtils.isNotBlank(bo.getAppName()), WcsExtApp::getAppName, bo.getAppName());
        lqw.eq(StringUtils.isNotBlank(bo.getHostAddr()), WcsExtApp::getHostAddr, bo.getHostAddr());
        lqw.eq(StringUtils.isNotBlank(bo.getCommPort()), WcsExtApp::getCommPort, bo.getCommPort());
        lqw.eq(bo.getHttpInterfacePort() != null, WcsExtApp::getHttpInterfacePort, bo.getHttpInterfacePort());
        lqw.eq(bo.getAPort() != null, WcsExtApp::getAPort, bo.getAPort());
        lqw.eq(bo.getBPort() != null, WcsExtApp::getBPort, bo.getBPort());
        lqw.eq(StringUtils.isNotBlank(bo.getAuthType()), WcsExtApp::getAuthType, bo.getAuthType());
        lqw.eq(StringUtils.isNotBlank(bo.getAuthData()), WcsExtApp::getAuthData, bo.getAuthData());
        lqw.eq(StringUtils.isNotBlank(bo.getFuid()), WcsExtApp::getFuid, bo.getFuid());
        lqw.eq(bo.getTextId() != null, WcsExtApp::getTextId, bo.getTextId());
        lqw.eq(bo.getRefrenceId() != null, WcsExtApp::getRefrenceId, bo.getRefrenceId());
        lqw.eq(bo.getUnitId() != null, WcsExtApp::getUnitId, bo.getUnitId());
        lqw.eq(bo.getDelFlag() != null, WcsExtApp::getDelFlag, bo.getDelFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getCreateBy()), WcsExtApp::getCreateBy, bo.getCreateBy());
        lqw.eq(bo.getCreateTime() != null, WcsExtApp::getCreateTime, bo.getCreateTime());
        lqw.eq(StringUtils.isNotBlank(bo.getUpdateBy()), WcsExtApp::getUpdateBy, bo.getUpdateBy());
        lqw.eq(bo.getUpdateTime() != null, WcsExtApp::getUpdateTime, bo.getUpdateTime());
        lqw.eq(StringUtils.isNotBlank(bo.getDeleteBy()), WcsExtApp::getDeleteBy, bo.getDeleteBy());
        lqw.eq(bo.getDeleteTime() != null, WcsExtApp::getDeleteTime, bo.getDeleteTime());
        lqw.eq(bo.getRowVersionStamp() != null, WcsExtApp::getRowVersionStamp, bo.getRowVersionStamp());
        lqw.eq(StringUtils.isNotBlank(bo.getRemark()), WcsExtApp::getRemark, bo.getRemark());
        return lqw;
    }

    /**
     * 新增外部系统定义
     */
    @Override
    public Boolean insertByBo(WcsExtAppBo bo) {
        WcsExtApp add = BeanUtil.toBean(bo, WcsExtApp.class);
        add.setFuid(IdUtil.fastUUID());
        validEntityBeforeSaveOrUpdate(add);
        return this.save(add);
    }

    /**
     * 修改外部系统定义
     */
    @Override
    public Boolean updateByBo(WcsExtAppBo bo) {
        // 由于 getByAppCode()，使用了appCode作为缓存，所以修改数据库的时候也要删除掉缓存。
        CacheUtils.evict(CacheNames.EXT_APP_CODE, bo.getAppCode());
        WcsExtApp update = BeanUtil.toBean(bo, WcsExtApp.class);
        validEntityBeforeSaveOrUpdate(update);
        return this.updateById(update);
    }

    /**
     * 批量删除外部系统定义
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        // 由于 getByAppCode()，使用了appCode作为缓存，所以删除数据库的时候也要删除掉缓存。
        for (Long id : ids) {
            WcsExtAppVo extAppVo = selectVoById(id);
            if (ObjectUtil.isNotNull(extAppVo)) {
                CacheUtils.evict(CacheNames.EXT_APP_CODE, extAppVo.getAppCode());
            }
        }
        return this.removeBatchByIds(ids);
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSaveOrUpdate(WcsExtApp entity) {
        // 做一些数据校验,如唯一约束
        LambdaQueryWrapper<WcsExtApp> lqw = Wrappers.lambdaQuery();
        lqw.eq(WcsExtApp::getAppCode, entity.getAppCode());
        lqw.ne(ObjectUtil.isNotNull(entity.getId()), WcsExtApp::getId, entity.getId());
        List<WcsExtApp> wcsExtAppList = this.baseMapper.selectList(lqw);
        if (CollUtil.isNotEmpty(wcsExtAppList)) {
            throw new ServiceException(StrUtil.format("应用代码已重复, code={}", entity.getAppCode()));
        }
        List<WcsAppClassVo> appClassVoList = appClassService.selectVoList(new WcsAppClassBo());
        if (CollUtil.isEmpty(appClassVoList)
            || appClassVoList.stream().map(WcsAppClassVo::getAppClass).noneMatch(appClassList -> appClassList.contains(entity.getAppClass()))) {
            throw new ServiceException(StrUtil.format("系统类别错误, class={}", entity.getAppClass()));
        }
    }
}
